package com.beemans.common.ext

import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.view.View
import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import com.beemans.common.app.CommonConfig
import com.beemans.common.ext.glide.GlideCallback
import com.beemans.common.ext.glide.GlideRequestListener
import com.beemans.common.utils.CommonCacheUtils
import com.blankj.utilcode.util.*
import com.bumptech.glide.load.resource.gif.GifDrawable
import com.bumptech.glide.request.target.Target
import com.tiamosu.fly.http.imageloader.ImageContextWrap
import com.tiamosu.fly.http.imageloader.ImageLoader
import com.tiamosu.fly.http.imageloader.imgCtxWrap
import com.tiamosu.fly.imageloader.glide.GlideRequest
import com.tiamosu.fly.imageloader.glide.ImageConfigImpl
import com.tiamosu.fly.imageloader.glide.getGlideRequests
import com.tiamosu.fly.utils.createFile
import com.tiamosu.fly.utils.launchIO
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.lang.ref.WeakReference
import kotlin.math.max

/**
 * @author tiamosu
 * @date 2021/3/12
 */

/**
 * Glide 加载图片
 */
fun ImageView.loadImage(
    any: Any?,
    imgCtxWrap: ImageContextWrap = this.imgCtxWrap,
    glideCallback: GlideCallback<Drawable>.() -> Unit = {}
) {
    val callback = GlideCallback<Drawable>().apply(glideCallback)
    ImageConfigImpl
        .load(any)
        .apply { callback.options?.invoke(this) }
        .addListener(GlideRequestListener(callback))
        .into(this)
        .build()
        .let { ImageLoader.loadImage(imgCtxWrap, it) }
}

/**
 * 加载圆形头像
 */
fun ImageView.loadCircleImage(
    any: Any?,
    callback: GlideCallback<Drawable>.() -> Unit = {}
) {
    loadImage(any) {
        callback.invoke(this)
        options {
            circleCrop()
            crossFade()
            GlideCallback<Drawable>().apply(callback).options?.invoke(this)
        }
    }
}

/**
 * 加载点九图
 */
fun ImageView.loadNinePatchImage(@DrawableRes resId: Int) {
    val weakReference = WeakReference(this)

    class ImageBean(
        val drawable: Drawable? = null,
        val isSave: Boolean = false
    )

    class LoadTask : ThreadUtils.SimpleTask<ImageBean>() {
        override fun doInBackground(): ImageBean {
            var drawable = CacheMemoryStaticUtils.get<Drawable>(resId.toString())
            if (drawable != null) {
                return ImageBean(drawable)
            }
            drawable = ContextCompat.getDrawable(Utils.getApp(), resId)
            return ImageBean(drawable, true)
        }

        override fun onSuccess(result: ImageBean) {
            result.drawable?.also { drawable ->
                weakReference.get()?.also { imageView ->
                    imageView.setImageDrawable(drawable)
                }
                if (result.isSave) {
                    CacheMemoryStaticUtils.put(resId.toString(), drawable)
                }
            }
        }
    }
    ThreadUtils.executeByIo(LoadTask())
}

/**
 * 通过 Glide 获取 Bitmap
 */
fun Any.getBitmap(
    imgCtxWrap: ImageContextWrap,
    width: Int = Target.SIZE_ORIGINAL,
    height: Int = Target.SIZE_ORIGINAL,
    block: GlideRequest<Bitmap>.() -> Unit = {},
    glideCallback: GlideCallback<Bitmap>.() -> Unit = {}
) {
    val glideRequest = imgCtxWrap.getGlideRequests ?: return
    val callback = GlideCallback<Bitmap>().apply(glideCallback)
    launchIO {
        glideRequest
            .asBitmap()
            .apply(block)
            .load(this)
            .listener(GlideRequestListener(callback))
            .apply {
                if (width != 0 && height != 0) {
                    submit(width, height)
                }
            }
    }
}

/**
 * 通过 Glide 获取 Drawable
 */
fun Any.getDrawable(
    imgCtxWrap: ImageContextWrap,
    width: Int = Target.SIZE_ORIGINAL,
    height: Int = Target.SIZE_ORIGINAL,
    block: GlideRequest<Drawable>.() -> Unit = {},
    glideCallback: GlideCallback<Drawable>.() -> Unit = {}
) {
    val glideRequest = imgCtxWrap.getGlideRequests ?: return
    val callback = GlideCallback<Drawable>().apply(glideCallback)
    launchIO {
        glideRequest
            .asDrawable()
            .apply(block)
            .load(this)
            .listener(GlideRequestListener(callback))
            .apply {
                if (width != 0 && height != 0) {
                    submit(width, height)
                }
            }
    }
}

/**
 * 通过 Glide 获取 Gif
 */
fun Any.getGif(
    imgCtxWrap: ImageContextWrap,
    width: Int = Target.SIZE_ORIGINAL,
    height: Int = Target.SIZE_ORIGINAL,
    block: GlideRequest<GifDrawable>.() -> Unit = {},
    glideCallback: GlideCallback<GifDrawable>.() -> Unit = {}
) {
    val glideRequest = imgCtxWrap.getGlideRequests ?: return
    val callback = GlideCallback<GifDrawable>().apply(glideCallback)
    launchIO {
        glideRequest
            .asGif()
            .apply(block)
            .load(this)
            .listener(GlideRequestListener(callback))
            .apply {
                if (width != 0 && height != 0) {
                    submit(width, height)
                }
            }
    }
}

/**
 * 通过 Glide 获取 File
 */
fun Any.getFile(
    imgCtxWrap: ImageContextWrap,
    width: Int = Target.SIZE_ORIGINAL,
    height: Int = Target.SIZE_ORIGINAL,
    block: GlideRequest<File>.() -> Unit = {},
    glideCallback: GlideCallback<File>.() -> Unit = {}
) {
    val glideRequest = imgCtxWrap.getGlideRequests ?: return
    val callback = GlideCallback<File>().apply(glideCallback)
    launchIO {
        glideRequest
            .asFile()
            .apply(block)
            .load(this)
            .listener(GlideRequestListener(callback))
            .apply {
                if (width != 0 && height != 0) {
                    submit(width, height)
                }
            }
    }
}

/**
 * 清除Glide缓存
 */
fun clearGlideCache(imgCtxWrap: ImageContextWrap = Utils.getApp().imgCtxWrap) {
    ImageConfigImpl
        .load(null)
        .clearMemory()
        .clearDiskCache()
        .build()
        .let { ImageLoader.clear(imgCtxWrap, it) }
}

/**
 * 开屏页清除Glide缓存
 */
fun clearCache(block: () -> Unit = {}) {
    if (CommonConfig.versionName != CommonCacheUtils.lastVersionName) {
        CommonCacheUtils.lastVersionName = CommonConfig.versionName
        clearGlideCache()
        block.invoke()
    }
}

/**
 * 布局生成 Bitmap
 */
fun View.view2Bitmap(isExactly: Boolean = true): Bitmap? {
    //测量使得view指定大小
    val specWidth = View.MeasureSpec.makeMeasureSpec(appScreenWidth, View.MeasureSpec.EXACTLY)
    val heightSize = if (isExactly) appScreenHeight else max(10000, appScreenHeight)
    val mode = if (isExactly) View.MeasureSpec.EXACTLY else View.MeasureSpec.AT_MOST
    val specHeight = View.MeasureSpec.makeMeasureSpec(heightSize, mode)
    measure(specWidth, specHeight)
    //调用layout方法布局后，可以得到view的尺寸大小
    layout(0, 0, measuredWidth, measuredHeight)
    //生成bitmap
    return Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.RGB_565)?.apply {
        Canvas(this).apply {
            drawColor(Color.WHITE)
        }.let(this@view2Bitmap::draw)
    }
}

/**
 * Bitmap 保存为图片
 */
fun Bitmap.toSaveImage(
    fileDirName: String = "SaveImg",
    fileName: String = "img.jpg",
    quality: Int = 80
): String? {
    kotlin.runCatching {
        val outFile = createFile(fileDirName, fileName)
        if (FileUtils.createOrExistsFile(outFile)) {
            val fos = FileOutputStream(outFile)
            val bos = BufferedOutputStream(fos)
            //压缩保存到本地
            compress(Bitmap.CompressFormat.JPEG, quality, bos)
            fos.flush()
            bos.flush()
            CloseUtils.closeIO(bos, fos)
            return outFile.path
        }
    }
    return null
}